package com.tedu.controller;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import com.tedu.element.ElementObj;
import com.tedu.element.bubble.Bubble;
import com.tedu.element.bubble.Explosion;
import com.tedu.element.item.Item;
import com.tedu.element.item.ItemType;
import com.tedu.element.map.GameMap;
import com.tedu.element.map.MapObj;
import com.tedu.element.player.Player;
import com.tedu.manager.ElementManager;
import com.tedu.manager.GameElement;
import com.tedu.manager.GameLoad;
import com.tedu.manager.MapLoader;
import com.tedu.show.GameConstants;

/**
 * @说明 游戏的主线程，用于控制游戏加载，游戏关卡，游戏运行时自动化
 * 游戏判定；游戏地图切换 资源释放和重新读取
 */
public class GameThread extends Thread {
    private ElementManager em;

    public GameThread() {
        em = ElementManager.getManager();
    }

    @Override
    public void run() {
        gameLoad();
        gameRun();
    }

    /**
     * 游戏的加载
     */
    private void gameLoad() {
        // 重置管理器
        em.init();

        //  加载关卡数据（地图和对象）
        MapLoader.MapData mapData = MapLoader.loadMap(GameController.selectedLevel);
        if (mapData == null) {
            System.err.println("地图加载失败，无法开始游戏！");
            return;
        }

        GameMap gameMap = mapData.getGameMap();
        if (gameMap != null) {
            // 将加载好的地图设置到管理器中
            em.setGameMap(gameMap);
            // 计算并更新窗口大小
            int mapWidth = gameMap.getGridWidth() * GameConstants.TILE_SIZE;
            int mapHeight = gameMap.getGridHeight() * GameConstants.TILE_SIZE;
            GameController.updateWindow(mapWidth, mapHeight);
        }

        // 根据地图配置加载玩家和其他对象
        loadObjectsFromConfig(mapData.getObjectConfigs());
    }

    /**
     * 根据从地图文件读取的配置来创建游戏对象（玩家、敌人等）
     *
     * @param configs 对象配置的 Map
     */
    private void loadObjectsFromConfig(Map<String, String> configs) {
        // 加载 Player_1
        if (configs.containsKey("player_1")) {
            ElementObj player1 = GameLoad.createPlayer(configs.get("player_1"), 1);
            if (player1 != null) {
                em.addElement(player1, GameElement.PLAYER);
            }
        }

        // 如果是双人模式，则加载 Player_2
        if (GameController.isMultiplayerMode && configs.containsKey("player_2")) {
            ElementObj player2 = GameLoad.createPlayer(configs.get("player_2"), 2);
            if (player2 != null) {
                em.addElement(player2, GameElement.PLAYER);
            }
        }
    }

    private void gameRun() {
        long gameTime = 0L;

        // 循环条件：线程未被中断
        while (!Thread.currentThread().isInterrupted()) {
            Map<GameElement, List<ElementObj>> all = em.getGameElements();
            List<ElementObj> players = all.get(GameElement.PLAYER);

            if (isGameOver(players, gameTime)) {
                GameController.switchPanel(GameController.GameState.GAME_OVER);
                break;
            }

            moveAndUpdate(all, gameTime);//	游戏元素自动化方法
            handleCollisions(); // 集中处理所有碰撞

            gameTime++;//唯一的时间控制
            try {
                sleep(10);//默认理解为 1秒刷新100次
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
    }

    private boolean isGameOver(List<ElementObj> players, long gameTime) {
        // 游戏刚开始时不判断，防止误判
        if (gameTime <= 10) {
            return false;
        }
        if (GameController.isMultiplayerMode) {
            // 双人模式，存活玩家数量小于等于 1 时结束
            return players.size() <= 1;
        } else {
            // 单人模式，没有存活玩家时结束
            return players.isEmpty();
        }
    }

    private void handleCollisions() {
        List<ElementObj> players = em.getElementsByKey(GameElement.PLAYER);
        List<ElementObj> bubbles = em.getElementsByKey(GameElement.BUBBLE);
        List<ElementObj> explosions = em.getElementsByKey(GameElement.EXPLOSION);
        List<ElementObj> items = em.getElementsByKey(GameElement.ITEM);
        GameMap gameMap = em.getGameMap();

        // 玩家与爆炸的碰撞
        checkPlayerExplosionCollision(players, explosions);
        // 玩家与道具的碰撞
        checkPlayerItemCollision(players, items);
        // 爆炸与泡泡的碰撞，用于触发连锁反应
        checkExplosionBubbleCollision(explosions, bubbles);
        // 爆炸与地图块的碰撞
        checkExplosionTileCollision(explosions, gameMap);
    }

    private void checkPlayerExplosionCollision(List<ElementObj> players, List<ElementObj> explosions) {
        for (ElementObj player : players) {
            for (ElementObj explosion : explosions) {
                if (player.pk(explosion)) {
                    player.setLive(false);
                }
            }
        }
    }

    private void checkPlayerItemCollision(List<ElementObj> players, List<ElementObj> items) {
        for (ElementObj player : players) {
            for (int i = items.size() - 1; i >= 0; i--) {
                ElementObj item = items.get(i);
                if (player.pk(item)) {
                    // 应用道具效果
                    ((Item) item).applyEffect((Player) player);
                    // 移除道具
                    item.setLive(false);
                }
            }
        }
    }

    private void checkExplosionBubbleCollision(List<ElementObj> explosions, List<ElementObj> bubbles) {
        // 临时列表，用于存储需要爆炸的泡泡
        List<Bubble> bubblesToExplode = new ArrayList<>();
        // 只检测碰撞，并将需要爆炸的泡泡添加到临时列表
        for (ElementObj explosion : explosions) {
            for (ElementObj bubbleObj : bubbles) {
                Bubble bubble = (Bubble) bubbleObj;
                if (explosion.pk(bubble) && !bubble.isExploding()) {
                    bubblesToExplode.add(bubble);
                }
            }
        }
        // 触发爆炸
        for (Bubble bubble : bubblesToExplode) {
            bubble.explode();
        }
    }

    private void checkExplosionTileCollision(List<ElementObj> explosions, GameMap gameMap) {
        // 临时列表，用于存储需要摧毁的地图块
        List<MapObj> tilesToDestroy = new ArrayList<>();
        for (ElementObj explosion : explosions) {
            int gridX = explosion.getGridX();
            int gridY = explosion.getGridY();
            MapObj tile = gameMap.getTile(gridX, gridY);

            if (tile != null && !tile.isInvincible()) {
                // 检查是否已在待摧毁列表
                if (!tilesToDestroy.contains(tile)) {
                    tilesToDestroy.add(tile);
                }
            }
        }

        for (MapObj tile : tilesToDestroy) {
            tile.setLive(false); // 销毁障碍物

            // 概率生成道具
            if (Math.random() < 0.3) {
                createItem(tile.getGridX(), tile.getGridY());
            }
        }
    }

    private void createItem(int gridX, int gridY) {
        // 随机选择道具类型
        ItemType type = ItemType.randomType();

        // 创建道具实例
        ElementObj obj = GameLoad.getObj("item");
        assert obj != null;

        // 传递参数格式: "gridX,gridY,type"
        String creationString = gridX + "," + gridY + "," + type;
        ElementObj element = obj.createElement(creationString);

        em.addElement(element, GameElement.ITEM);
    }


    //	游戏元素自动化方法
    public void moveAndUpdate(Map<GameElement, List<ElementObj>> all, long gameTime) {
        for (GameElement ge : GameElement.values()) {
            List<ElementObj> list = all.get(ge);
            for (int i = list.size() - 1; i >= 0; i--) {
                ElementObj obj = list.get(i);
                if (!obj.isLive()) {
                    obj.die();
                    list.remove(i);
                    continue;
                }
                obj.model(gameTime);
            }
        }
    }
}





